<template>
    <div class="tableRow">
        <el-row class="select-list" v-permission="'system:user:query'">
            <el-form :inline="true" ref="selectForm" :label-position="'right'" label-width="80px"
                     :model="selectFormModel" size="mini">
                <el-form-item label="用户名" prop="userName">
                    <el-input v-model="selectFormModel.userName" placeholder="用户名" style="width: 200px" clearable
                              @keyup.enter.native="onSearch"/>
                </el-form-item>
                <el-form-item label="手机号码" prop="phoneNumber">
                    <el-input v-model="selectFormModel.phoneNumber" placeholder="手机号码" style="width: 200px" clearable
                              @keyup.enter.native="onSearch"/>
                </el-form-item>
                <el-form-item label="性别" prop="sex">
                    <el-select value="" v-model="selectFormModel.sex" placeholder="性别" style="width: 200px">
                        <el-option label="男" value="0"/>
                        <el-option label="女" value="1"/>
                        <el-option label="保密" value="2"/>
                    </el-select>
                </el-form-item>
                <el-form-item label="用户状态" prop="status">
                    <el-select value="" v-model="selectFormModel.status" placeholder="用户状态" style="width: 200px">
                        <el-option label="正常" value="0"/>
                        <el-option label="停用" value="1"/>
                    </el-select>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" icon="el-icon-search" size="mini" plain round @click="onSearch">搜索
                    </el-button>
                    <el-button type="warning" icon="el-icon-refresh" size="mini" plain round
                               @click="onRefreshSelectForm()">重置
                    </el-button>
                </el-form-item>
            </el-form>
        </el-row>
        <el-row class="toolbar">
            <el-button type="primary" icon="el-icon-plus" size="mini" plain @click="handleAdd"
                       v-permission="'system:user:add'">
                新增
            </el-button>
            <el-button type="info" icon="el-icon-edit" :disabled="dialog.isBatchEditDisabled" size="mini" plain
                       @click="handleEdit" v-permission="'system:user:edit'"> 编辑
            </el-button>
            <el-button type="danger" icon="el-icon-delete" :disabled="dialog.isBatchRemoveDisabled" size="mini" plain
                       @click="handleBatchDelete" v-permission="'system:user:remove'"> 删除
            </el-button>
            <el-button type="success" icon="el-icon-upload" size="mini" plain @click="handleImport"
                       v-permission="'system:user:import'"> 导入
            </el-button>
            <el-button type="warning" icon="fa fa-download" size="mini" plain @click="handleExport"
                       v-permission="'system:user:export'"> 导出
            </el-button>
        </el-row>
        <data-table ref="dataTable"
                    :api="getUserList"
                    :options="options"
                    :pagination.sync="page"
                    :columns="columns"
                    :operates="operates"
                    :query="selectFormModel"
                    @handleSelectionChange="handleSelectionChange"
        />

        <transition name="el-fade-in">
            <el-dialog :title="dialog.title" :visible.sync="dialog.dialogFormVisible"
                       :modal-append-to-body="false"
                       :destroy-on-close="false"
                       @close="closeDialog"
                       width="600px">
                <el-form :model="userModel" ref="userForm" label-width="100px" :rules="userFormRules" size="small ">
                    <el-form-item label="用户名" prop="userName">
                        <el-input v-model="userModel.userName" placeholder="用户名" :disabled="dialog.isEdit"/>
                    </el-form-item>
                    <el-form-item label="姓名" prop="name">
                        <el-input v-model="userModel.name" placeholder="姓名"/>
                    </el-form-item>

                    <el-form-item label="部门" prop="deptId">
                        <!--el-tree-select  文档地址 https://ayiaq1.github.io/el-tree-select/website/#/components/ElTreeSelect-->
                        <el-tree-select v-model="userModel.deptId" :selectParams="dialog.selectParams"
                                        :treeParams="dialog.treeParams"
                                        @searchFun="searchFun" ref="treeSelect"/>
                    </el-form-item>

                    <el-form-item label="角色" prop="roleIds">
                        <el-select value="" v-model="userModel.roleIds" multiple filterable clearable placeholder="角色">
                            <el-option
                                    v-for="item in dialog.roles"
                                    :key="item.id"
                                    :label="item.roleName"
                                    :value="item.id">
                            </el-option>
                        </el-select>
                    </el-form-item>

                    <el-form-item label="岗位" prop="postIds">
                        <el-select value="" v-model="userModel.postIds" multiple filterable clearable placeholder="岗位">
                            <el-option
                                    v-for="item in dialog.posts"
                                    :key="item.id"
                                    :label="item.postName"
                                    :value="item.id">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="状态" prop="status">
                        <el-switch v-model="userModel.status" active-color="#13ce66" inactive-color="#ff4949"
                                   active-text="正常"
                                   inactive-text="停用"
                                   active-value="0"
                                   inactive-value="1"/>
                    </el-form-item>
                    <el-form-item label="邮箱" prop="email">
                        <el-input v-model="userModel.email" placeholder="邮箱"/>
                    </el-form-item>
                    <el-form-item label="手机" prop="phoneNumber">
                        <el-input v-model="userModel.phoneNumber" prefix-icon="el-icon-phone"
                                  placeholder="手机"/>
                    </el-form-item>
                    <el-form-item label="性别" prop="sex">
                        <el-select value="" v-model="userModel.sex" placeholder="性别">
                            <el-option label="男" value="0"/>
                            <el-option label="女" value="1"/>
                            <el-option label="保密" value="2"/>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="备注" prop="remark">
                        <el-input v-model="userModel.remark" placeholder="备注" maxlength="100"/>
                    </el-form-item>
                </el-form>
                <div slot="footer" class="dialog-footer">
                    <el-button @click="dialog.dialogFormVisible=false" size="medium">取 消</el-button>
                    <el-button type="primary" @click="submitForm" size="medium">确 定</el-button>
                </div>
            </el-dialog>
        </transition>

        <transition name="el-fade-in">
            <el-dialog :title="dialog.title" :visible.sync="dialog.dialogImportVisible"
                       :modal-append-to-body="false"
                       :destroy-on-close="false"
                       custom-class="body-wrapper"
                       @close="closeUploadDialog"
                       width="500px">

                <el-upload
                        drag
                        ref="upload"
                        :action="src"
                        :show-file-list="true"
                        :auto-upload="false"
                        :headers="headers"
                        accept=".xls,.xlsx"
                        :on-success="uploadSuccess"
                        :on-exceed="handleExceed"
                        :on-error="uploadError"
                        :limit="1"
                >
                    <i class="el-icon-upload"/>
                    <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>

                    <div class="el-upload__tip" slot="tip">
                        <el-alert
                                title="只能上传xls/xlsx文件"
                                type="warning"
                                show-icon>
                        </el-alert>
                        <br/>
                        <el-alert type="info"
                                  show-icon
                                  :closable="false">
                            <span>没有模板？ 点击&nbsp;<a href="#" @click="downloadTemplate">下载模板</a></span>
                        </el-alert>
                    </div>
                </el-upload>

                <div slot="footer" class="dialog-footer">
                    <el-button @click="dialog.dialogImportVisible=false" size="medium">取 消</el-button>
                    <el-button type="primary" @click="submitUpload" size="medium">确 定</el-button>
                </div>
            </el-dialog>
        </transition>
    </div>
</template>
<script lang="ts">
    //https://github.com/kaorun343/vue-property-decorator
    import {Component, Ref, Vue} from "vue-property-decorator";
    import DataTable from "@/components/DataTable/DataTable.vue";
    import {
        addUser,
        checkEmailUnique,
        checkPhoneUnique,
        checkUserNameUnique,
        downloadUserImportTemplate,
        exportUser,
        getUserList,
        getUserPost,
        getUserRole,
        removeUser,
        resetPwd,
        updateUser
    } from "@/api/user";
    import {deptTreeSelectData} from "@/api/dept";
    import {getPostList} from "@/api/post";
    import {getRoleList} from "@/api/role";
    import axios from "axios";
    import store from '@/store';

    @Component({components: {DataTable}})
    export default class User extends Vue {
        private getUserList: Function = getUserList;
        @Ref("userForm") private userForm: any;
        @Ref("selectForm") private selectForm: any;
        @Ref("treeSelect") private treeSelect: any;
        @Ref("dataTable") private dataTable: any;
        @Ref("upload") private upload: any;

        get src() {
            return process.env.VUE_APP_BASE_API + "/system/user/import";
        }

        headers: any = {
            "Authorization": store.getters.token
        };

        columns: any = [
            {label: "ID", prop: "id", sortable: "custom"},
            {label: "用户名", prop: "userName", sortable: "custom"},
            {label: "姓名", prop: "name", sortable: "custom"},
            {
                label: "部门", prop: "dept", formatter: function (row: any, column: any) {
                    if (row && row.dept && row.dept.deptName) {
                        return row.dept.deptName;
                    } else {
                        return "无";
                    }
                }
            },
            {label: "邮箱", prop: "email", sortable: "custom"},
            {label: "手机", prop: "phoneNumber", sortable: "custom"},
            {
                label: "性别", prop: "sex", sortable: "custom", formatter: function (row: any, column: any) {
                    if (row && row.sex === "0") {
                        return "男";
                    } else if (row && row.sex === "1") {
                        return "女";
                    } else {
                        return "保密";
                    }
                }
            },
            {
                label: "状态", prop: "status", sortable: "custom", render: function (createElement: any, row: any) {
                    if (row && row.row && row.row.status === "0") {
                        return createElement("el-tag", {
                                attrs: {
                                    type: "success"
                                }
                            }, ["正常"]
                        );
                    } else if (row && row.row && row.row.status === "1") {
                        return createElement("el-tag", {
                                attrs: {
                                    type: "warning"
                                }
                            }, ["停用"]
                        );
                    } else {
                        return createElement("el-tag", {
                                attrs: {
                                    type: "danger"
                                }
                            }, ["未知"]
                        );
                    }
                }
            },
            {label: "创建时间", prop: "createTime", sortable: "custom", width: 160},
            {label: "备注", prop: "remark", sortable: "custom"}
        ];

        // table 的参数
        options: any = {
            stripe: true, // 是否为斑马纹 table
            loading: false, // 是否添加表格loading加载动画
            highlightCurrentRow: true, // 是否支持当前行高亮显示
            multipleSelect: true, // 是否支持列表项选中功能
        };


        // 分页参数
        page: any = {
            pageNum: 1,
            pageSize: 10,
            pageArray: [10, 20, 50, 100]
        };

        //按钮操作组
        operates: any = {
            title: "操作",
            width: 'auto',
            fixed: "right",
            list: [
                {
                    label: "编辑",
                    type: "warning",
                    icon: "el-icon-edit",
                    plain: true,
                    disabled: (index: any, row: any) => {
                        return row && row.id === 1;
                    },
                    permission: "system:user:edit",
                    method: (index: any, row: any) => {
                        this.handleEdit(index, row);
                    }
                },
                {
                    label: "删除",
                    type: "danger",
                    icon: "el-icon-delete",
                    plain: true,
                    disabled: (index: any, row: any) => {
                        return row && row.id === 1;
                    },
                    permission: "system:user:remove",
                    method: (index: any, row: any) => {
                        this.handleDelete(index, row);
                    }
                },
                {
                    label: "重置",
                    type: "primary",
                    icon: "el-icon-key",
                    plain: true,
                    disabled: (index: any, row: any) => {
                        return row && row.id === 1;
                    },
                    permission: "system:user:edit",
                    method: (index: any, row: any) => {
                        this.handleReset(index, row);
                    }
                }
            ]
        };
        selectFormModel: any = {
            userName: "",
            status: "",
            phoneNumber: "",
            sex: "",
        };
        dialog: any = {
            dialogFormVisible: false,
            dialogImportVisible: false,
            title: "对话框",
            isEdit: false,
            isBatchEditDisabled: true,
            isBatchRemoveDisabled: true,
            formData: {},
            selectParams: {
                clearable: true,
                placeholder: "请选择部门"
            },
            treeParams: {
                clickParent: true,
                filterable: true,
                accordion: true,
                data: [],
                props: {
                    children: "children",
                    label: "label",
                    disabled: "disabled",
                    value: "id"
                }
            }
        };

        userModel: any = {
            userName: "",
            name: "",
            email: "",
            phoneNumber: "",
            sex: "",
            deptId: "",
            roleIds: [],
            status: 0,
            remark: "",
            postIds: []
        };
        userFormRules: any = {
            userName: [
                {required: true, message: "用户名不能为空", trigger: ["blur", "change"]},
                {
                    required: true,
                    pattern: /^[a-zA-Z0-9_]*$/,//可以写正则表达式
                    message: "用户名只能是字母或者数字",
                    trigger: ["blur", "change"]
                },
                {validator: this.validateUserNameUnique, trigger: "blur"}
            ],
            name: [
                {required: true, message: "姓名不能为空", trigger: ["blur", "change"]}
            ],
            email: [
                {required: true, message: "邮箱不能为空", trigger: ["blur", "change"]},
                {type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"]},
                {validator: this.validateEmailUnique, trigger: "blur"}
            ],
            phoneNumber: [
                {required: true, message: "手机号码不能为空", trigger: "blur"},
                {
                    required: true,
                    pattern: /^1[345678]\d{9}$/,//可以写正则表达式
                    message: "目前只支持中国大陆的手机号码",
                    trigger: ["blur", "change"]
                },
                {validator: this.validatePhoneUnique, trigger: "blur"}
            ],
            sex: [
                {required: true, message: "性别不能为空", trigger: ["blur", "change"]}
            ]
        };

        /*验证用户名是否唯一*/
        validateUserNameUnique(rule: any, value: any, callback: any) {
            checkUserNameUnique({
                userName: value,
                id: this.userModel.id
            }).then((res: any) => {
                if (res.data && res.data === '0') {
                    callback();
                } else {
                    callback(new Error("用户名已经存在"));
                }
            }).catch((err: any) => {
                console.log(err);
                callback(new Error("用户名已经存在"));
            })
        };

        /*验证手机号码是否唯一*/
        validatePhoneUnique(rule: any, value: any, callback: any) {
            checkPhoneUnique({
                phoneNumber: value,
                id: this.userModel.id
            }).then((res: any) => {
                if (res.data && res.data === '0') {
                    callback();
                } else {
                    callback(new Error("手机号码已经存在"));
                }
            }).catch((err: any) => {
                console.log(err);
                callback(new Error("手机号码已经存在"));
            })
        };

        /*验证邮箱是否唯一*/
        validateEmailUnique(rule: any, value: any, callback: any) {
            checkEmailUnique({
                email: value,
                id: this.userModel.id
            }).then((res: any) => {
                if (res.data && res.data === '0') {
                    callback();
                } else {
                    callback(new Error("邮箱已经存在"));
                }
            }).catch((err: any) => {
                console.log(err);
                callback(new Error("邮箱已经存在"));
            })
        };

        handleEdit(index: number, row: any): void {
            //编辑
            let self = this;
            this.userModel = Object.assign({}, row || this.dialog.formData[0]);
            this.userModel.dept = [];
            self.dialog.title = "编辑用户";
            self.dialog.isEdit = true;
            let id = (row && row.id) ? row.id : self.dialog.formData[0].id;

            axios.all(
                [
                    getUserRole({"id": id}),
                    deptTreeSelectData(),
                    getUserPost({"id": id})
                ]
            ).then(axios.spread((role: any, dept: any, post: any) => {
                if (role.data) {
                    self.userModel.roleIds = role.data.roleIds;
                    self.dialog.roles = role.data.roles;
                }

                if (self.userModel && self.userModel.roleIds === null) {
                    self.userModel.roleIds = [];
                }
                if (dept.data) {
                    self.dialog.treeParams.data = dept.data;
                }

                if (post.data) {
                    self.userModel.postIds = post.data.postIds;
                    self.dialog.posts = post.data.posts;
                }

                self.dialog.dialogFormVisible = true;
            })).catch((e) => {
                console.log(e);
            });
        };

        handleAdd(): void {
            //打开新增
            let self = this;
            self.dialog.title = "新增用户";
            self.dialog.isEdit = false;

            axios.all([getRoleList({"status": 0}), deptTreeSelectData(), getPostList({"status": 0})])
                .then(axios.spread((role: any, dept: any, post: any) => {
                    self.dialog.roles = role.rows;
                    self.dialog.treeParams.data = dept.data;
                    self.dialog.posts = post.rows;
                    self.dialog.dialogFormVisible = true;
                })).catch((e) => {
                console.log(e);
            });
        }

        handleBatchDelete(): void {
            //删除
            this.$confirm("确定要删除选定用户？", "警告", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            }).then(() => {
                let ids: Array<any> = [];
                this.dialog.formData.forEach((item: any, index: number) => {
                    ids[index] = item.id;
                });
                return removeUser({"ids": ids});
            }).then((response: any) => {
                this.dataTable.refresh();
                this.$message.success(response.msg);
            }).catch((e) => {
                console.log(e);
            });
        }

        searchFun(value: any): void {
            this.treeSelect.filterFun(value);
        }

        onSearch(): void {
            this.dataTable.refresh();
        }

        onRefreshSelectForm(): void {
            //恢复搜索默认信息
            this.selectForm.resetFields();
            this.onSearch();
        }

        closeDialog(): void {
            this.$nextTick(() => {
                this.dialog.treeParams.data = [];
                this.reset();
            });
        }

        submitForm(): void {
            let self = this;
            this.userForm.validate((valid: boolean) => {
                if (valid) {
                    self.userModel.roles = [];
                    self.userModel.dept = [];
                    self.userModel.posts = [];
                    if (self.dialog.isEdit) {
                        //编辑
                        updateUser(self.userModel).then((response: any) => {
                            self.dataTable.refresh();
                            self.reset();
                            self.dialog.dialogFormVisible = false;
                            self.$message.success(response.msg);
                        }).catch((e) => {
                            console.log(e);
                        });
                    } else {
                        //新增
                        addUser(self.userModel).then((response: any) => {
                            self.dataTable.refresh();
                            self.reset();
                            self.dialog.dialogFormVisible = false;
                            self.$message.success(response.msg);
                        }).catch((e) => {
                            console.log(e);
                        });
                    }
                }
            });
        }

        handleDelete(index: number, row: any): void {
            //删除
            this.$confirm("确定要删除该用户？", "警告", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            }).then(() => {
                return removeUser({"ids": [row.id]});
            }).then((response: any) => {
                this.dataTable.refresh();
                this.$message.success(response.msg);
            }).catch((e) => {
                console.log(e);
            });
        }

        handleReset(index: number, row: any): void {
            //删除
            this.$confirm("确定要重置该用户的登录密码吗？", "警告", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            }).then(() => {
                return resetPwd({'id': row.id});
            }).then((response: any) => {
                this.dataTable.refresh();
                this.$message.success(response.msg);
            }).catch((e) => {
                console.log(e);
            });
        }

        handleSelectionChange(val: any): void {
            //返回选中对象
            if (val) {
                this.dialog.isBatchRemoveDisabled = val.length <= 0;
                this.dialog.isBatchEditDisabled = val.length !== 1;
            }
            this.dialog.formData = val;
        }

        reset(): void {
            this.userModel = {
                userName: "",
                name: "",
                email: "",
                phoneNumber: "",
                sex: "",
                deptId: "",
                roleIds: [],
                status: 0,
                remark: "",
                postIds: []
            };
            (this as any).resetForm("userForm");
        }

        /*导出excel*/
        handleExport(): void {
            let self = this;
            self.$confirm("确定要导出当前查询的所有用户信息吗？", "提示", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "info"
            }).then(() => {
                self.selectFormModel.pageNum = null;
                self.selectFormModel.pageSize = null;
                self.selectFormModel.orderByColumn = "id";
                self.selectFormModel.isAsc = "asc";

                return exportUser(self.selectFormModel);
            }).then((response: any) => {
                console.log(response);
                if (response && response.data) {
                    (self as any).$download(response.data.fileName);
                }
            }).catch((e) => {
                console.log(e);
            });
        }

        /*下载用户导入模板*/
        downloadTemplate(): void {
            let self = this;
            downloadUserImportTemplate().then((response: any) => {
                console.log(response);
                if (response && response.data) {
                    (self as any).$download(response.data.fileName);
                }
            }).catch((e) => {
                console.log(e);
            });
        }

        /*打开导入对话框*/
        handleImport(): void {
            this.dialog.title = "用户导入";
            this.dialog.dialogFormVisible = false;
            this.dialog.dialogImportVisible = true;
        }

        /*上传*/
        submitUpload() {
            this.upload.submit();
        }

        /*上传成功*/
        uploadSuccess(res, file) {
            console.log(res);
            if (res.result) {//上传成功
                this.$message.success(`导入成功，${res.msg}`);
            } else {//上传失败
                this.$message.warning(`导入失败，${res.msg}`);
                this.upload.clearFiles();
            }
        }

        /*文件上传失败*/
        uploadError(res, file) {
            console.log(res.message);
            let result = JSON.parse(res.message);

            this.$message.error(`导入失败，${result.msg}`);
        }

        handleExceed(files, fileList) {
            this.$message.warning(`当前限制选择 3 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`);
        }

        closeUploadDialog() {
            this.$nextTick(() => {
                this.upload.clearFiles();
            });
        }
    }
</script>

<style scoped lang="scss">
    a {
        color: #8c939d;

        &:hover {
            color: #b4bccc;
            text-decoration: underline;
        }
    }
</style>

